﻿using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

//winS TODO: 调整列宽的功能还未添加

namespace winS.UnityEditor.UIElement
{
    /// <summary>
    /// 带有(列)表头的表格
    /// </summary>
    public class Table : VisualElement
    {
        public static readonly float margin = 2f;
        public static readonly Color32 headerColor = ColorLevelUtility.GetColor(8);

        public override VisualElement contentContainer => scrollView;

        private float[] widths;

        private readonly Row headerContainer;
        private readonly ScrollView scrollView;
        private readonly List<Header> headersList = new List<Header>();
        private readonly List<TableData> tableDataList = new List<TableData>();

        internal Table()
        {
            hierarchy.Add(headerContainer = EditorElementUtility.elementFactory.CreateRowWithName("表头容器", 0f));
            headerContainer.style.flexShrink = 0f;
            headerContainer.RegisterCallback<GeometryChangedEvent>(_ => CalculateColumnWidth());
            hierarchy.Add(scrollView = EditorElementUtility.elementFactory.CreateScrollView(ScrollViewMode.Vertical));
        }

        public void SetHeaders(params KeyValuePair<string, float>[] headers)
        {
            Clear();
            headersList.Clear();
            tableDataList.Clear();

            widths = new float[headers.Length];
            for (int i = 0; i < headers.Length; i++)
            {
                Header header = new Header(headers[i].Key);
                float width = headers[i].Value;
                if (width > 0f) header.style.SetWidth(width);
                else header.style.flexGrow = 1f;
                headerContainer.Add(header);
                headersList.Add(header);
                if (i == headers.Length - 1) return;

                headerContainer.Add(new Splitline(i));
            }
        }

        public void Add(TableData tableData)
        {
            tableData.table = this;
            scrollView.Add(tableData);
            tableDataList.Add(tableData);
            for (int i = 0; i < tableData.childCount; i++) tableData.ElementAt(i).style.width = widths[i];
        }

        public void CalculateColumnWidth()
        {
            for (int i = 0; i < widths.Length; i++) widths[i] = headersList[i].layout.width;

            foreach (var tableData in tableDataList)
            {
                for (int i = 0; i < tableData.childCount; i++)
                {
                    tableData.ElementAt(i).style.width = widths[i];
                }
            }
        }

        public class TableData : VisualElement
        {
            public Table table { get; internal set; }

            public TableData()
            {
                style.flexDirection = FlexDirection.Row;
                style.SetBorderBottomWdith(margin);
            }

            public void AddData(VisualElement data)
            {
                VisualElement item = new VisualElement();
                if (childCount != 0) item.style.SetMarginLeft(margin);
                item.Add(data);
                Add(item);
                if (table != null) for (int i = 0; i < childCount; i++) ElementAt(i).style.width = table.widths[i];
            }
        }

        internal class Header : VisualElement
        {
            private readonly string headerName;

            public Header(string headerName)
            {
                this.headerName = headerName;
                style.SetBackgroundColor(ColorLevelUtility.GetColor(8));
                Add(EditorElementUtility.elementFactory.CreateLabel(headerName, TextAnchor.MiddleCenter));
            }

            public override string ToString() => headerName;
        }
        internal class Splitline : VisualElement
        {
            private readonly int index;

            private bool dragging;
            private Vector3 startPosition;

            public Splitline(int index)
            {
                this.index = index;
                style.SetMinWidth(margin);
                //style.SetCursor(MouseCursor.ResizeHorizontal);

                //RegisterCallback<PointerDownEvent>(OnPointerDownCallback);
                //RegisterCallback<PointerMoveEvent>(OnPointerMoveCallback);
                //RegisterCallback<PointerUpEvent>(OnPointerUpCallback);
            }

            private void OnPointerUpCallback(PointerUpEvent evt)
            {
                dragging = false;
                this.ReleaseMouse();
            }

            private void OnPointerDownCallback(PointerDownEvent pointerDownEvent)
            {
                dragging = true;
                this.CaptureMouse();
                startPosition = pointerDownEvent.localPosition;
            }

            private void OnPointerMoveCallback(PointerMoveEvent pointerMoveEvent)
            {
                if (!dragging) return;
                Vector3 vector = pointerMoveEvent.localPosition - startPosition;
                pointerMoveEvent.StopPropagation();
            }
        }
    }
}
